class Player extends GameObject {
    constructor(playground, x, y, radius, color, speed, is_me) {
        super();
        this.playground = playground;
        this.ctx = playground.game_map.ctx;
        this.x = x;
        this.y = y;
        this.vx = 0;
        this.vy = 0;
        this.damage_x = 0;
        this.damage_y = 0;
        this.damage_speed = 0;
        this.friction = 0.9;
        this.move_length = 0;
        this.radius = radius;
        this.color = color;
        this.speed = speed;
        this.is_me = is_me;
        this.eps = 0.1;
        this.spent_time = 0;
        this.use_key_to_move = false;
        this.key_v = [0, 0];

        this.hold_w = false;
        this.hold_s = false;
        this.hold_a = false;
        this.hold_d = false;

        this.cur_skill = "fireball";
    }

    start() {
        if (this.is_me) {
            this.add_listening_events();

            this.img = new Image();
            this.img.src = this.playground.root.settings.photo;
        } else {
            let tx = Math.random() * this.playground.width;
            let ty = Math.random() * this.playground.height;
            this.move_to(tx, ty);
        }
    }

    add_listening_events() {
        let outer = this;
        this.playground.game_map.$canvas.on("contextmenu", function () {
            return false;
        });

        this.playground.game_map.$canvas.mousedown(function (e) {
            // 左键 1    右键 3
            if (e.which === 3) {
                outer.use_key_to_move = false;
                outer.move_to(e.clientX, e.clientY);
            } else if (e.which === 1) {
                if (outer.cur_skill === "fireball") {
                    outer.shoot_fireball(e.clientX, e.clientY);
                }
            }
        });

        $(window).keydown(function (e) {
            // q 81    w 87    a 65    d 68    s 83
            if (e.which === 81) {
                outer.cur_skill = "fireball";
            }

            if (e.which === 87) { // w
                outer.use_key_to_move = true;
                outer.hold_w = true;
                outer.key_v[1] = -1;
            } else if (e.which === 83) { // s
                outer.use_key_to_move = true;
                outer.hold_s = true;
                outer.key_v[1] = 1;
            }

            if (e.which === 65) { // a
                outer.use_key_to_move = true;
                outer.hold_a = true;
                outer.key_v[0] = -1;
            } else if (e.which === 68) { // d
                outer.use_key_to_move = true;
                outer.hold_d = true;
                outer.key_v[0] = 1;
            }
        });

        $(window).keyup(function (e) {
            // q 81    w 87    a 65    d 68    s 83
            if (e.which === 87 || e.which === 83) {
                outer.key_v[1] = 0;
                if (e.which === 87) {
                    outer.hold_w = false;
                } else {
                    outer.hold_s = false;
                }
            } else if (e.which === 65 || e.which === 68) {
                outer.key_v[0] = 0;
                if (e.which === 65) {
                    outer.hold_a = false;
                } else {
                    outer.hold_d = false;
                }
            }
        });
    }

    shoot_fireball(tx, ty) {
        let x = this.x, y = this.y;
        let radius = this.radius * 0.2;
        let dist = this.get_dist(tx, ty, this.x, this.y);
        let vx = (tx - this.x) / dist;
        let vy = (ty - this.y) / dist;
        let color = "orange";
        let speed = this.speed * 3;
        let move_length = this.playground.height;
        let damage = this.playground.height * 0.01;
        new FireBall(this.playground, this, x, y, radius, vx, vy, color, speed, move_length, damage);
    }

    get_dist(x1, y1, x2, y2) {
        let dx = x1 - x2;
        let dy = y1 - y2;
        return Math.sqrt(dx * dx + dy * dy);
    }

    move_to(tx, ty) {
        this.move_length = this.get_dist(this.x, this.y, tx, ty);
        this.vy = (ty - this.y) / this.move_length;
        this.vx = (tx - this.x) / this.move_length;
    }

    update() {

        if (this.hold_a ^ this.hold_d) {
            if (this.hold_a) this.key_v[0] = -1;
            else this.key_v[0] = 1;
        }

        if (this.hold_w ^ this.hold_s) {
            if (this.hold_w) this.key_v[1] = -1;
            else this.key_v[1] = 1;
        }

        this.spent_time += this.timedelta / 1000;
        if (!this.is_me && this.spent_time > 4 && Math.random() < 1 / 200) {
            this.shoot_fireball(this.playground.players[0].x, this.playground.players[0].y);
        }

        if (this.damage_speed > this.eps) {
            this.vx = 0;
            this.vy = 0;
            this.move_length = 0;
            this.x += this.damage_x * this.damage_speed * this.timedelta / 1000;
            this.y += this.damage_y * this.damage_speed * this.timedelta / 1000;
            this.damage_speed *= this.friction;
        } else {
            if (this.use_key_to_move) {
                let mo = Math.sqrt(this.key_v[0] * this.key_v[0] + this.key_v[1] * this.key_v[1]);
                if (mo !== 0) {
                    this.x += this.key_v[0] / mo * this.speed * this.timedelta / 1000;
                    this.y += this.key_v[1] / mo * this.speed * this.timedelta / 1000;
                    if (this.x > this.playground.width) this.x = this.playground.width;
                    else if (this.x < 0) this.x = 0;

                    if (this.y > this.playground.height) this.y = this.playground.height;
                    else if (this.y < 0) this.y = 0;
                }
            } else {
                if (this.move_length < this.eps) {
                    this.vx = 0;
                    this.vy = 0;
                    if (!this.is_me) {
                        let tx = Math.random() * this.playground.width;
                        let ty = Math.random() * this.playground.height;
                        this.move_to(tx, ty);
                    }
                } else {
                    let moved = Math.min(this.speed * this.timedelta / 1000, this.move_length);
                    this.x += this.vx * moved;
                    this.y += this.vy * moved;
                    this.move_length -= moved;
                }
            }
        }

        this.render();
    }

    freely_falling_body() {
        this.x += this.vx;
        this.y += this.vy;
        this.vy += 0.3;
        if (this.y + this.radius >= this.playground.height) {
            this.vy = -this.vy + 0.3;
        }
    }

    is_attacked(sin, cos, damage) {
        for (let i = 0; i < 10 + Math.random() * 5; i++) {
            let x = this.x, y = this.y;
            let radius = this.radius * Math.random() * 0.1;
            let angle = Math.PI * 2 * Math.random();
            let vx = Math.cos(angle), vy = Math.sin(angle);
            let speed = this.speed * 3;
            new Particle(this.playground, x, y, radius, vx, vy, this.color, speed);
        }

        this.radius -= damage;
        if (this.radius <= 10) {
            this.on_destroy();
            this.destroy();
            return false;
        }


        this.damage_x = cos;
        this.damage_y = sin;
        this.damage_speed = damage * 200;
    }

    render() {
        if (this.is_me) {
            this.ctx.save();
            this.ctx.beginPath();
            this.ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
            this.ctx.stroke();
            this.ctx.clip();
            this.ctx.drawImage(this.img, this.x - this.radius, this.y - this.radius, this.radius * 2, this.radius * 2);
            this.ctx.restore();
        } else {
            this.ctx.beginPath();
            this.ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
            this.ctx.fillStyle = this.color;
            this.ctx.fill();
        }
    }

    on_destroy() {
        if (this.is_me) {
            this.playground.game_map.$canvas.off();
            this.playground.game_map.$canvas.on("contextmenu", function () {
                return false;
            });
        }
        for (let i = 0; i < this.playground.players.length; i++) {
            if (this === this.playground.players[i]) {
                this.playground.players.splice(i, 1);
                break;
            }
        }
    }
}